package com.duobaoyu.dby.supply.message.listener.hander.refund;

import com.alibaba.fastjson.JSON;
import com.duobaoyu.dby.channel.adapter.enums.biz.product.GoodsStatusEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.refund.AfterSaleTypeEnum;
import com.duobaoyu.dby.channel.adapter.util.ChannelCodeUtils;
import com.duobaoyu.dby.channel.boundary.bean.refund.result.AfterSaleAttributesResult;
import com.duobaoyu.dby.channel.common.util.SupplyCollectionUtils;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.mybatis.config.IdGeneratorSnowflake;
import com.duobaoyu.dby.common.mybatis.util.EnumUtils;
import com.duobaoyu.dby.resource.remote.common.enums.BizTypeEnum;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.bo.OrderBO;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.bo.OrderProductBO;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.bo.OrderQueryInBO;
import com.duobaoyu.dby.supply.biz.client.boundary.refund.AfterSaleBoundaryClient;
import com.duobaoyu.dby.supply.biz.enums.AfterSaleSourceEnum;
import com.duobaoyu.dby.supply.biz.enums.OrderParentTypeEnum;
import com.duobaoyu.dby.supply.biz.producer.constant.SupplyChainMQConstants;
import com.duobaoyu.dby.supply.biz.producer.message.ApplyAfterSaleMessage;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.service.refund.AfterSaleService;
import com.duobaoyu.dby.supply.common.biz.bo.refund.AfterSaleAuditRuleBO;
import com.duobaoyu.dby.supply.common.biz.bo.refund.AfterSaleContactInfoBO;
import com.duobaoyu.dby.supply.common.biz.bo.refund.AfterSaleCreateInBO;
import com.duobaoyu.dby.supply.common.biz.bo.refund.AfterSaleCreateSplitInBO;
import com.duobaoyu.dby.supply.core.dinger.annotation.DingerTalk;
import com.duobaoyu.dby.supply.core.rocketmq.handler.AbstractClusterMessageHandler;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 *
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class OrderCancelAfterSaleMessageHandler extends AbstractClusterMessageHandler<ApplyAfterSaleMessage> {

    private final OrderService orderService;

    private final AfterSaleService afterSaleService;

    private final AfterSaleBoundaryClient afterSaleBoundaryClient;

    private final IdGeneratorSnowflake idGeneratorSnowflake;
    private final int CONSUME_MAX_TIMES = 5;

    @Override
    public String getTopic() {
        return SupplyChainMQConstants.SupplyChainTopic.ORDER_TOPIC;
    }

    @Override
    public String getTag() {
        return SupplyChainMQConstants.SupplyChainTopic.AfterSaleTag.CANCEL_ORDER_APPLY_AFTER_SALE;
    }

    @Override
    @DingerTalk(title = "订单取消售后消息Consumer")
    public boolean messageHandler(ApplyAfterSaleMessage afterSaleMessage, MessageExt messageExt) {
        if (messageExt.getReconsumeTimes() < CONSUME_MAX_TIMES) {
            try {
                OrderQueryInBO orderQuery = new OrderQueryInBO();
                orderQuery.setSupplyTradeSn(afterSaleMessage.getSupplyTradeSn());
                orderQuery.setOrderSnList(afterSaleMessage.getOrderSnList());
                orderQuery.setParentType(OrderParentTypeEnum.AFTER_SPLIT.getValue());
                orderQuery.setReturnProduct(true);
                orderQuery.setReturnConsignee(true);
                List<OrderBO> orders = orderService.list(orderQuery);
                // 排除最底层 & 拆分前订单
                List<OrderBO> mainOrders = new ArrayList<>(orders);

                List<AfterSaleCreateSplitInBO.Item> afterSaleItemSummary = mainOrders.stream()
                        .map(e -> {
                            Map<String, AfterSaleAttributesResult.Attribute> itemAfterSaleAttributeMap;
                            List<OrderProductBO> orderProducts = e.getOrderProductList();
                            if (ChannelCodeUtils.channelAfterSaleReasonCodeNotNull(e.getChannelCode())) {
                                List<AfterSaleAttributesResult> afterSaleAttributes = afterSaleBoundaryClient.queryAfterSaleReason(e, orderProducts);
                                itemAfterSaleAttributeMap = afterSaleAttributes.stream().flatMap(attributes -> attributes.getAttributes().stream())
                                        .collect(Collectors.toMap(AfterSaleAttributesResult.Attribute::getSkuCode, Function.identity()));
                            } else {
                                itemAfterSaleAttributeMap = Maps.newHashMap();
                            }
                            return orderProducts.stream().map(sku -> {
                                AfterSaleCreateSplitInBO.Item item = new AfterSaleCreateSplitInBO.Item();
                                item.setOrderSn(e.getOrderSn());
                                item.setSkuCode(sku.getSkuCode());
                                item.setApplyNum(sku.getSkuNum());
                                Optional<AfterSaleAttributesResult.ReasonDetail> reasonOptional = getChannelAfterSaleReasonCode(sku, itemAfterSaleAttributeMap);
                                if (reasonOptional.isPresent()) {
                                    AfterSaleAttributesResult.ReasonDetail reason = reasonOptional.get();
                                    item.setReasonCode(reason.getChannelAfterSaleReasonCode());
                                    item.setReasonName(reason.getChannelAfterSaleReason());
                                }
                                item.setGoodStatus(GoodsStatusEnum.REFUND_WAIT_SELLER_SEND.getValue());
                                item.setApplyRefundAmount(sku.getChannelPayAmount());
                                return item;
                            }).collect(Collectors.toList());
                        }).flatMap(Collection::stream).collect(Collectors.toList());

                OrderBO order = SupplyCollectionUtils.getSingleDataFirst(mainOrders, OrderBO::new);
                AfterSaleCreateSplitInBO splitIn = new AfterSaleCreateSplitInBO();
                splitIn.setAfterSaleSource(AfterSaleSourceEnum.SYSTEM.getValue());
                splitIn.setSupplyTradeSn(order.getBizTradeSn());
                splitIn.setServerName(BizTypeEnum.SUPPLY_CHAIN.name().toLowerCase());
                splitIn.setShowServerName(order.getShowServerName());
                splitIn.setBizAfterSaleSn(String.valueOf(idGeneratorSnowflake.snowflakeId()));
                splitIn.setAfterSaleType(AfterSaleTypeEnum.REFUND.getValue());
                splitIn.setItems(afterSaleItemSummary);
                // 申请人信息
                AfterSaleContactInfoBO contactInfo = new AfterSaleContactInfoBO();
                contactInfo.setCustomerMobilePhone(order.getOrderAddress().getRecipientMobile());
                contactInfo.setCustomerContactName(order.getOrderAddress().getRecipientName());
                Map<String, AfterSaleContactInfoBO> contactInfoMap = Maps.newHashMap();
                contactInfoMap.put(order.getOrderSn(), contactInfo);
                splitIn.setCustomerInfoMap(contactInfoMap);
                List<AfterSaleCreateInBO> afterSales = afterSaleService.afterSaleSplit(splitIn, mainOrders);
                afterSales.forEach(e -> {
                    AfterSaleAuditRuleBO audit = new AfterSaleAuditRuleBO();
                    audit.setAutoAudit(true);
                    audit.setLateSubmitTime(Long.valueOf(CommonConstants.ZERO));
                    e.setAuditRule(audit);
                });
                afterSaleService.afterSaleApply(afterSales);
                return Boolean.TRUE;
            } catch (Exception e) {
                log.warn("consume order cancel afterSale message throw exception.msgId={}, param = {}", messageExt.getMsgId(), JSON.toJSONString(afterSaleMessage));
                throw e;
            }
        }
        return true;
    }

    private static Optional<AfterSaleAttributesResult.ReasonDetail> getChannelAfterSaleReasonCode(OrderProductBO sku, Map<String, AfterSaleAttributesResult.Attribute> itemAfterSaleAttributeMap) {
        AfterSaleAttributesResult.Attribute attribute = itemAfterSaleAttributeMap.getOrDefault(sku.getSkuCode(), new AfterSaleAttributesResult.Attribute());
        List<AfterSaleAttributesResult.AfterSaleReason> afterSaleReasons = attribute.getAfterSaleReasons();
		if (CollectionUtils.isEmpty(afterSaleReasons)) {
			return Optional.empty();
		}
        return afterSaleReasons.stream()
                .filter(attr -> EnumUtils.eq(AfterSaleTypeEnum.REFUND, attr.getAfterSaleType().getValue()))
                .map(AfterSaleAttributesResult.AfterSaleReason::getReasonDetails)
                .flatMap(Collection::stream)
                .findFirst();
    }
}
